#include "InputManager.hpp"


InputManager* InputManager::m_inputManager = NULL;

InputManager::InputManager(const sf::Input& input):
m_input(input),
m_keys(),
m_mouseButtons(),
m_pressedKeys(),
m_pressedMouseButtons(),
m_events()
{
}

InputManager::~InputManager()
{
}
		
InputManager& InputManager::instance()
{
	return *m_inputManager;
}

void InputManager::createInstance(const sf::Input& input)
{
	if(m_inputManager == NULL)
	{
		m_inputManager = new InputManager(input);
		m_inputManager->bind();
	}
}

void InputManager::destroyInstance()
{
	if(m_inputManager != NULL)
		delete m_inputManager;
}

void InputManager::bind()
{
    /// /// KEYBOARD /// ///
    m_keys["A"] = sf::Key::A;   // letters
	m_keys["B"] = sf::Key::B;
	m_keys["C"] = sf::Key::C;
	m_keys["D"] = sf::Key::D;
	m_keys["E"] = sf::Key::E;
	m_keys["F"] = sf::Key::F;
	m_keys["G"] = sf::Key::G;
	m_keys["H"] = sf::Key::H;
	m_keys["I"] = sf::Key::I;
	m_keys["J"] = sf::Key::J;
	m_keys["K"] = sf::Key::K;
	m_keys["L"] = sf::Key::L;
	m_keys["M"] = sf::Key::M;
	m_keys["N"] = sf::Key::N;
	m_keys["O"] = sf::Key::O;
	m_keys["P"] = sf::Key::P;
	m_keys["Q"] = sf::Key::Q;
	m_keys["R"] = sf::Key::R;
	m_keys["S"] = sf::Key::S;
	m_keys["T"] = sf::Key::T;
	m_keys["U"] = sf::Key::U;
	m_keys["V"] = sf::Key::V;
	m_keys["W"] = sf::Key::W;
	m_keys["X"] = sf::Key::X;
	m_keys["Y"] = sf::Key::Y;
	m_keys["Z"] = sf::Key::Z;

	m_keys["Num0"] = sf::Key::Num0;   // Numbers
	m_keys["Num1"] = sf::Key::Num1;
	m_keys["Num2"] = sf::Key::Num2;
	m_keys["Num3"] = sf::Key::Num3;
	m_keys["Num4"] = sf::Key::Num4;
	m_keys["Num5"] = sf::Key::Num5;
	m_keys["Num6"] = sf::Key::Num6;
	m_keys["Num7"] = sf::Key::Num7;
	m_keys["Num8"] = sf::Key::Num8;
	m_keys["Num9"] = sf::Key::Num9;

	m_keys["Escape"] = sf::Key::Escape;
	m_keys["LControl"] = sf::Key::LControl;
	m_keys["LShift"] = sf::Key::LShift;
	m_keys["LAlt"] = sf::Key::LAlt;
	m_keys["LSystem"] = sf::Key::LSystem;
	m_keys["RControl"] = sf::Key::RControl;
	m_keys["RShift"] = sf::Key::RShift;
	m_keys["RAlt"] = sf::Key::RAlt;
	m_keys["RSystem"] = sf::Key::RSystem;
	m_keys["Menu"] = sf::Key::Menu;
	m_keys["LBracket"] = sf::Key::LBracket;
	m_keys["RBracket"] = sf::Key::RBracket;
	m_keys["SemiColon"] = sf::Key::SemiColon;
	m_keys["Comma"] = sf::Key::Comma;
	m_keys["Period"] = sf::Key::Period;
	m_keys["Quote"] = sf::Key::Quote;
	m_keys["Slash"] = sf::Key::Slash;
	m_keys["BackSlash"] = sf::Key::BackSlash;
	m_keys["Tilde"] = sf::Key::Tilde;
	m_keys["Equal"] = sf::Key::Equal;
	m_keys["Dash"] = sf::Key::Dash;
	m_keys["Space"] = sf::Key::Space;
	m_keys["Return"] = sf::Key::Return;
	m_keys["Back"] = sf::Key::Back;
	m_keys["Tab"] = sf::Key::Tab;
	m_keys["PageUp"] = sf::Key::PageUp;
	m_keys["PageDown"] = sf::Key::PageDown;
	m_keys["End"] = sf::Key::End;
	m_keys["Home"] = sf::Key::Home;
	m_keys["Insert"] = sf::Key::Insert;
	m_keys["Delete"] = sf::Key::Delete;
	m_keys["Add"] = sf::Key::Add;
	m_keys["Subtract"] = sf::Key::Subtract;
	m_keys["Multiply"] = sf::Key::Multiply;
	m_keys["Divide"] = sf::Key::Divide;
	m_keys["Left"] = sf::Key::Left;
	m_keys["Right"] = sf::Key::Right;
	m_keys["Up"] = sf::Key::Up;
	m_keys["Down"] = sf::Key::Down;

	m_keys["Numpad0"] = sf::Key::Numpad0;
	m_keys["Numpad1"] = sf::Key::Numpad1;
	m_keys["Numpad2"] = sf::Key::Numpad2;
	m_keys["Numpad3"] = sf::Key::Numpad3;
	m_keys["Numpad4"] = sf::Key::Numpad4;
	m_keys["Numpad5"] = sf::Key::Numpad5;
	m_keys["Numpad6"] = sf::Key::Numpad6;
	m_keys["Numpad7"] = sf::Key::Numpad7;
	m_keys["Numpad8"] = sf::Key::Numpad8;
	m_keys["Numpad9"] = sf::Key::Numpad9;

	m_keys["F1"] = sf::Key::F1;
	m_keys["F2"] = sf::Key::F2;
	m_keys["F3"] = sf::Key::F3;
	m_keys["F4"] = sf::Key::F4;
	m_keys["F5"] = sf::Key::F5;
	m_keys["F6"] = sf::Key::F6;
	m_keys["F7"] = sf::Key::F7;
	m_keys["F8"] = sf::Key::F8;
	m_keys["F10"] = sf::Key::F10;
	m_keys["F11"] = sf::Key::F11;
	m_keys["F12"] = sf::Key::F12;
	m_keys["F13"] = sf::Key::F13;
	m_keys["F14"] = sf::Key::F14;
	m_keys["F15"] = sf::Key::F15;
	m_keys["Pause"] = sf::Key::Pause;
	
	/// MOUSE BUTTONS
	m_mouseButtons["left"] = sf::Mouse::Left;
	m_mouseButtons["right"] = sf::Mouse::Right;
}


void InputManager::update()
{
	// keyboard
	std::map<std::string,sf::Key::Code>::iterator itor = m_keys.begin();
	for(; itor != m_keys.end(); ++itor)
	{
		// TRIGGER RELEASED
		if(m_pressedKeys.find(itor->first) != m_pressedKeys.end() && !m_input.IsKeyDown(itor->second))
		{
			m_pressedKeys.erase(itor->first);
			m_events.push_back(InputEvent(TRIGGERED_RELEASED_EVENT_TYPE,itor->second));
		}
		// TRIGGER PRESSED
		else if(m_pressedKeys.find(itor->first) == m_pressedKeys.end() && m_input.IsKeyDown(itor->second))
		{
			m_events.push_back(InputEvent(TRIGGERED_PRESSED_EVENT_TYPE,itor->second));
			m_pressedKeys.insert(itor->first);
		}
		
		// PRESSED
		if(m_input.IsKeyDown(itor->second))
			m_events.push_back(InputEvent(PRESSED_EVENT_TYPE,itor->second));
		
		// RELEASED
		else
			m_events.push_back(InputEvent(RELEASED_EVENT_TYPE,itor->second));	
	}	
	
	// mouse
	std::map<std::string,sf::Mouse::Button>::iterator itor2 = m_mouseButtons.begin();
	for(; itor2 != m_mouseButtons.end(); ++itor2)
	{
		// TRIGGER RELEASED
		if(m_pressedMouseButtons.find(itor2->first) != m_pressedMouseButtons.end() && !m_input.IsMouseButtonDown(itor2->second))
		{
			m_pressedMouseButtons.erase(itor2->first);
			m_events.push_back(InputEvent(TRIGGERED_RELEASED_EVENT_TYPE,itor2->second));
		}
		// TRIGGER PRESSED
		else if(m_pressedMouseButtons.find(itor2->first) == m_pressedMouseButtons.end() && m_input.IsMouseButtonDown(itor2->second))
		{
			m_events.push_back(InputEvent(TRIGGERED_PRESSED_EVENT_TYPE,itor2->second));
			m_pressedMouseButtons.insert(itor2->first);
		}
		
		// PRESSED
		if(m_input.IsMouseButtonDown(itor2->second))
			m_events.push_back(InputEvent(PRESSED_EVENT_TYPE,itor2->second));
		
		// RELEASED
		else
			m_events.push_back(InputEvent(RELEASED_EVENT_TYPE,itor2->second));	
	}
}

void InputManager::flushEvents()
{
	m_events.clear();
}

bool InputManager::checkEvent(const InputEvent &event)
{
	for(std::list<InputEvent>::iterator itor = m_events.begin(); itor != m_events.end(); ++itor)
		if(*itor == event)
			return true;
		
	return false;
}

sf::Vector2i InputManager::posMouse() const
{
	return sf::Vector2i(m_input.GetMouseX(),m_input.GetMouseY());
}

